home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Light ROM 1
/
LIGHT-ROM 1 (Amiga Library Services)(1994).iso
/
ffdisks
/
d971.lha
/
Yak
/
Source
/
handler.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-12-21
|
14KB
|
566 lines
/*
* handler.c
*
* Routines to set up handler.
* Part of Yak.
*
* Martin W. Scott, 9/92.
*/
#include <exec/types.h>
#include <exec/exec.h>
#include <hardware/custom.h>
#include <hardware/dmabits.h>
#include <devices/console.h>
#include <devices/input.h>
#include <devices/inputevent.h>
#include <libraries/commodities.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <graphics/displayinfo.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/layers.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/commodities.h>
#include <string.h>
#include "yak.h"
#include "beep.h"
static void __inline TurnMouseOn (void);
static void __inline TurnMouseOff (void);
static void __regargs IntuiOp (void (*routine) (APTR), APTR parameter);
static void __regargs PopToFront (struct Window *win);
static struct Window *WindowUnderMouse (void);
static BOOL __regargs StrGadgetActive (struct Window *w);
extern struct Custom __far custom;
#define REBLANKCOUNT 10 /* how long to wait to reblank mouse */
void (*intui_routine) (APTR); /* for intui_op's */
APTR intui_parameter;
CxObj *clickobj;
ULONG clicksigflag, intuiopsigflag;
static BYTE clicksigbit, intuiopsigbit = -1;
static struct Task *thistask;
static BOOL misspop;
/* for screen click-to-back */
void __stdargs
MyScreenToBack (struct Screen *scr)
{
struct Screen *ns = scr->NextScreen;
struct Window *win;
if (!ns)
ns = IntuitionBase->FirstScreen;
if (ns != scr)
{
ScreenToBack (scr);
if (scractivate && ns)
{
win = WindowUnderMouse();
if (win)
ActivateWindow (win);
else
if (ns->FirstWindow)
ActivateWindow (ns->FirstWindow);
}
}
}
/* Stub for Intuition routines - passes request on to main task.
* DO NOT CALL WHILE FORBID()ING!
* Thanks to Eddy Carroll for this.
*/
#define WTB(win) IntuiOp(WindowToBack, win)
#define WTF(win) IntuiOp(WindowToFront, win)
#define WACT(win) IntuiOp((void (*)(APTR))ActivateWindow, win)
#define STB(scr) IntuiOp(MyScreenToBack, scr)
#define STF(scr) IntuiOp(ScreenToFront, scr)
static void __regargs
IntuiOp (void (*routine) (APTR), APTR parameter)
{
BYTE oldpri = SetTaskPri (thistask, 21);
intui_routine = routine;
intui_parameter = parameter;
Signal (thistask, intuiopsigflag);
SetTaskPri (thistask, oldpri);
}
/* pattern-matching on screen/window titles */
#define IsXXXScreen(scr, pat) (scr && (!scr->Title || MatchPattern(pat, scr->Title)))
#define IsClickScreen(scr) IsXXXScreen(scr, clickscrpat)
#define IsAutoScreen(scr) IsXXXScreen(scr, autoscrpat)
#define IsXXXWindow(win, pat) (!win->Title || MatchPattern(pat, win->Title))
#define IsPopWindow(win) IsXXXWindow(win,popwinpat)
#define IsClickWindow(win) IsXXXWindow(win,clickwinpat)
#define INTERRUPT void __interrupt __saveds
/* when is a window safe to bring to front and not already at front? */
#define OkayToPop(win) (!win->ReqCount && !(win->Flags & (WFLG_MENUSTATE|WFLG_BACKDROP)) \
&& win->WLayer->ClipRect && win->WLayer->ClipRect->Next)
/* WindowToFront only if no requester, not backdrop, not already front... */
static void __regargs
PopToFront (struct Window *win)
{
/* want to avoid popping immediately after mousebutton/keyboard */
if (misspop)
misspop = FALSE;
else if (OkayToPop (win))
{
/* Does it pass pattern? */
if (IsPopWindow (win))
WTF (win);
}
}
/* modified from DMouse */
/* expects multitasking to be Forbid()en */
static struct Screen *mousescr; /* the screen under the mouse */
void
ScreenUnderMouse( void )
{
for (mousescr = IntuitionBase->FirstScreen ;
mousescr && mousescr->TopEdge > 0 && mousescr->MouseY < 0;
mousescr = mousescr->NextScreen);
}
static struct Window *
WindowUnderMouse ( void )
{
struct Layer *layer = NULL;
for (mousescr = IntuitionBase->FirstScreen ;
mousescr && mousescr->TopEdge > 0 && mousescr->MouseY < 0;
mousescr = mousescr->NextScreen);
if (mousescr)
layer = WhichLayer(&mousescr->LayerInfo, mousescr->MouseX, mousescr->MouseY);
return (layer ? (struct Window *) layer->Window : NULL);
}
/* does active window have an active string gadget? */
static BOOL __regargs
StrGadgetActive (struct Window *w)
{
struct Gadget *g = w->FirstGadget;
for (; g; g = g->NextGadget)
if ((g->GadgetType & STRGADGET) && (g->Flags & GFLG_SELECTED))
return TRUE;
return FALSE;
}
/* activate window under mouse */
/* context sensitive; why tells routine how to behave */
/* can be AUTO, KEY, SCREEN, RMBACT */
#define AW IntuitionBase->ActiveWindow
#define AWS IntuitionBase->ActiveWindow->WScreen
#define FS IntuitionBase->FirstScreen
#define FSW IntuitionBase->FirstScreen->FirstWindow
void __regargs
ActivateMouseWindow (BYTE why)
{
struct Window *win;
BOOL forbidden = TRUE;
Forbid ();
if (win = WindowUnderMouse ()) /* window exists to activate */
{
/* either window is not active or auto-activating - need to pop? */
if (win->Flags & WFLG_WINDOWACTIVE) /* already active - needs popped? */
{
if (why == AUTO && autopop && IsAutoScreen (win->WScreen))
{
Permit (), forbidden = FALSE;
PopToFront (win);
}
}
else if (why != AUTO || IsAutoScreen (win->WScreen))
{
/* window is not active, should we try to activate it? */
/* AW is IntuitionBase->ActiveWindow */
if (!AW ||
!(AW->Flags & WFLG_MENUSTATE) && /* not showing menus */
!(why == KEY && StrGadgetActive (AW))) /* no str gad active */
{
/* finally... */
Permit (), forbidden = FALSE;
/* do autopop? */
if (why == AUTO && autopop)
PopToFront (win);
if (why == KEY)
ActivateWindow (win); /* need this to avoid losing keys */
else
WACT (win); /* ...activate window */
}
}
}
else
/* no window under mouse... */
{
if (mousescr && mousescr->FirstWindow &&
((why == SCREEN) || (why == RMBACT && AW && AWS != mousescr)))
{
Permit (), forbidden = FALSE;
WACT (mousescr->FirstWindow); /* ...activate window */
}
}
if (forbidden)
Permit ();
}
static UWORD __chip posctldata[4];
static struct SimpleSprite simplesprite =
{posctldata, 0, 0, 0, 0};
static BOOL mouseoff; /* is mouse off? (MB_SPRITES only) */
static void __inline
TurnMouseOn () /* restore mouse-pointer */
{
if (mouseblank == MB_SPRITES) /* really dirty blanking */
{ /* but guaranteed to work... */
if (mouseoff)
{
Forbid ();
WaitTOF ();
ON_SPRITE;
Permit ();
}
}
/* else using FreeSprite solution - unblanks when needed */
mouseoff = FALSE;
}
static void __inline
TurnMouseOff () /* blank mouse-pointer */
{
if (!mouseoff) /* no point in turning it off twice... */
{
Forbid ();
if (mouseblank == MB_SPRITES)
{
WaitTOF ();
OFF_SPRITE;
custom.spr[0].dataa = custom.spr[0].datab = 0;
}
else
{
FreeSprite (0);
GetSprite (&simplesprite, 0);
}
Permit ();
mouseoff = TRUE;
}
}
static BOOL blanked;
static struct Screen *blankscr;
/* blank display, by putting up a black screen */
/* this screen's displaymode is cloned from front screen */
void
BlankScreen ()
{
ULONG modeid = INVALID_ID;
if (blankscr)
ScreenToFront (blankscr);
else
{
Forbid ();
if (FS)
modeid = GetVPModeID (&(FS->ViewPort));
Permit ();
if (modeid == INVALID_ID)
modeid = LORES_KEY;
if (blankscr = OpenScreenTags (NULL, SA_Depth, 1,
SA_Quiet, TRUE,
SA_Behind, TRUE,
SA_DisplayID, modeid,
TAG_DONE))
{
SetRGB4 (&blankscr->ViewPort, 0, 0, 0, 0);
ScreenToFront (blankscr);
blanked = TRUE;
}
}
OFF_SPRITE;
custom.spr[0].dataa = custom.spr[0].datab = 0;
}
/* unblank display, i.e. close our screen */
void
UnBlankScreen ()
{
if (blankscr)
CloseScreen (blankscr);
blankscr = NULL;
blanked = FALSE;
ON_SPRITE;
}
#define ALL_BUTTONS (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RBUTTON|IEQUALIFIER_MIDBUTTON)
#define KEY_QUAL (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT \
|IEQUALIFIER_CONTROL \
|IEQUALIFIER_LALT|IEQUALIFIER_RALT \
|IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND)
#define ALL_QUALS (ALL_BUTTONS|KEY_QUAL)
/* the input handler itself */
INTERRUPT
Handler (CxMsg * CxMsg, CxObj * CO)
{
static struct timeval lastclick; /* last left-button click */
static WORD apcount; /* timer events since last mousemove */
struct InputEvent *ev;
ev = (struct InputEvent *) CxMsgData (CxMsg);
if (ev->ie_Class == IECLASS_TIMER)
{
/*** AUTO-ACTIVATE/POP, SCREENBLANK, MOUSEBLANK ***/
if (!(ev->ie_Qualifier & ALL_QUALS) && autopoint && !apcount--)
{
ActivateMouseWindow (AUTO);
}
if (blanktimeout && !--blankcount) /* blank screen? */
{
BlankScreen ();
blankcount = blanktimeout; /* reset counter */
} /* in case sceen opens on top */
if (mouseblank && !--mblankcount) /* blank mouse? */
{
mouseoff = FALSE; /* force reblank */
TurnMouseOff ();
/* in case someone else turns it on, reset counter */
mblankcount = REBLANKCOUNT;
}
}
else
if ((ev->ie_Class == IECLASS_RAWKEY) && !(ev->ie_Code & IECODE_UP_PREFIX))
{
/*** MOUSEBLANK, KEYACTIVATE, KEYCLICK ***/
blankcount = blanktimeout; /* reset blanking countdown */
if (blanked) /* turn off screen-blanking */
UnBlankScreen ();
if (mouseblank)
if (ev->ie_Qualifier & IEQUALIFIER_LCOMMAND)
{
/* this allows use of keyboard to move mouse */
mblankcount = mblanktimeout;
TurnMouseOn ();
}
else
TurnMouseOff (); /* blank the mouse */
if (click_volume)
Signal (thistask, clicksigflag);
if (keyactivate) /* perform key-activate */
ActivateMouseWindow (KEY);
}
else if (ev->ie_Class == IECLASS_RAWMOUSE)
{
/*** CLICKTOFRONT/BACK, AUTOACTIVATE ***/
/* restore screen/mouse pointer */
blankcount = blanktimeout; /* reset blanking countdowns */
mblankcount = mblanktimeout;
if (blanked) /* turn off screen-blanking */
UnBlankScreen ();
if (mouseoff)
TurnMouseOn (); /* not needed for MB_COPPER */
/* window/screen cycling... */
/* maybe should check for depth gadgets? nah... */
if (!(ev->ie_Qualifier & KEY_QUAL))
{
if (!(ev->ie_Qualifier & ALL_BUTTONS))
{
apcount = autopoint_delay; /* reset auto-activate count */
}
else
/* a button - check out clicktofront etc. */
{
/* mustn't be Forbid()en when calling window op */
BOOL forbidden = TRUE;
Forbid ();
misspop = TRUE;
apcount = -1; /* button - wait for move */
if (clicktofront && ev->ie_Code == IECODE_LBUTTON)
{
if (DoubleClick (lastclick.tv_secs,
lastclick.tv_micro,
ev->ie_TimeStamp.tv_secs,
ev->ie_TimeStamp.tv_micro))
{
struct Window *win = WindowUnderMouse ();
if (win)
{
Permit (), forbidden = FALSE;
mousescr = win->WScreen;
if (IsClickScreen ( mousescr ))
{
if (!(win->Flags & WFLG_BACKDROP)
&& IsClickWindow (win) && OkayToPop (win))
{
WTF (win); /* musn't be Forbid()en here */
}
else
if (screencycle)
{
STF (mousescr); /* musn't be Forbid()en here */
}
}
}
else
{
ScreenUnderMouse();
Permit (), forbidden = FALSE;
if (IsClickScreen ( mousescr ) && screencycle)
{
STF (mousescr); /* musn't be Forbid()en here */
}
}
lastclick.tv_secs = 0;
lastclick.tv_micro = 0;
}
else
{
lastclick.tv_secs = ev->ie_TimeStamp.tv_secs;
lastclick.tv_micro = ev->ie_TimeStamp.tv_micro;
}
}
else
if (ev->ie_Code == IECODE_RBUTTON &&
(ev->ie_Qualifier & IEQUALIFIER_LEFTBUTTON))
{
struct Window *win = WindowUnderMouse ();
if (win)
{
Permit (), forbidden = FALSE;
mousescr = win->WScreen;
if (IsClickScreen ( mousescr ))
{
if (!(win->Flags & WFLG_BACKDROP)
&& (win->NextWindow || win->WScreen->FirstWindow != win))
{
WTB(win); /* musn't be Forbid()en here */
}
else
if (screencycle)
{
STB (mousescr); /* musn't be Forbid()en here */
}
}
}
else
{
ScreenUnderMouse();
Permit (), forbidden = FALSE;
if (IsClickScreen ( mousescr ) && screencycle)
{
ev->ie_Class = IECLASS_NULL;
STB (mousescr);
}
}
}
else
if ((rmbactivate && (ev->ie_Code == IECODE_RBUTTON)) ||
(mmbactivate && (ev->ie_Code == IECODE_MBUTTON)))
{
Permit (), forbidden = FALSE;
ActivateMouseWindow (RMBACT);
}
if (forbidden)
Permit ();
}
}
}
else
if (ev->ie_Class == IECLASS_DISKINSERTED)
{
blankcount = blanktimeout; /* reset blanking countdown */
if (blanked) /* turn off screen-blanking */
UnBlankScreen ();
}
}
/* close resources allocated for handler */
void
EndHandler ()
{
if (clickobj)
DeleteCxObj (clickobj);
FreeAudio ();
if (intuiopsigbit != -1)
FreeSignal (intuiopsigbit);
if (clicksigbit != -1)
FreeSignal (clicksigbit);
UnBlankScreen ();
TurnMouseOn ();
}
/* open resources needed for handler */
BOOL
InitHandler ()
{
if (((clicksigbit = AllocSignal (-1)) != -1) &&
((intuiopsigbit = AllocSignal (-1)) != -1) &&
AllocAudio ())
{
thistask = FindTask (NULL); /* initialize liason structure */
clicksigflag = 1 << clicksigbit;
intuiopsigflag = 1 << intuiopsigbit;
clickobj = CxCustom (Handler, 0L);
AttachCxObj (broker, clickobj);
return TRUE;
}
EndHandler ();
return FALSE;
}